package controls.visu;

import gui.visu.components.TimePanel;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;

import data.Constants;
import data.visu.DisplayDataList;
import data.visu.TimeData;
import data.visu.structures.TimeTick;
import data.visu.utils.TimeHMSConvertor;


/**
 * @author Charles Perin
 * 29 mars 2011
 * LIMSI - INRIA Rennes
 * charles.perin@free.fr
 *
 */
public class TimeLadderControl {


	private DisplayDataList displayDataList;
	private TimePanel timePanel;
	private TimeData timeData;

	public TimeLadderControl(TimeData timeData, TimePanel timePanel, DisplayDataList displayDataList) {
		this.timeData = timeData;
		this.displayDataList = displayDataList;
		this.timePanel = timePanel;
	}

	public void showTimeLadder() {
		int tMin = displayDataList.getxMinView();
		int tMax = displayDataList.getxMaxView();
		SortedMap<Integer,TimeTick> ticksInView = buildTicksInView(tMin, tMax);
		SortedMap<Integer, TimeTick> ticksDisplayed = Collections.synchronizedSortedMap(new TreeMap<Integer, TimeTick>());
		int nbTimeValues = 0;
		int levelAccepted = 0;
		while(nbTimeValues<Constants.NB_TIME_VALUES_MAX && levelAccepted<10){
			Iterator<Integer> iter = ticksInView.keySet().iterator();
			while(iter.hasNext()){
				int currentFrame = iter.next();
				TimeTick tick = ticksInView.get(currentFrame);
				if(tick.getLevel()==levelAccepted){
					ticksDisplayed.put(currentFrame, tick);
					nbTimeValues++;
				}
			}
			levelAccepted++;
		}
		
		Iterator<Integer> iter = ticksDisplayed.keySet().iterator();
		while(iter.hasNext()){
			int currentFrame = iter.next();
			TimeTick tick = ticksDisplayed.get(currentFrame);
			tick.setxValueOnRef(convertXValueOnRef(currentFrame));
		}
		
		//suppression des HMS des ticks mineurs
		int nbTicksHMS=ticksDisplayed.size();
		int levelMax=-1;
		while(nbTicksHMS>Constants.NB_TIME_VALUES_MAX && levelMax != 0){
			levelMax=0;
			//calcul du level maximum
			Iterator<Integer> iter3 = ticksDisplayed.keySet().iterator();
			while(iter3.hasNext()){
				int currentFrame = iter3.next();
				TimeTick tick = ticksDisplayed.get(currentFrame);
				if(tick.getLevel()>levelMax)levelMax = tick.getLevel();
			}
			
			//suppression des trop grands levels
			Iterator<Integer> iter4 = ticksDisplayed.keySet().iterator();
			while(iter4.hasNext()){
				int currentFrame = iter4.next();
				TimeTick tick = ticksDisplayed.get(currentFrame);
				if(tick.getLevel()==levelMax){
					iter4.remove();
					nbTicksHMS--;
				}
			}
		}
		displayDataList.setTimeLadderParamsForActiveDisplayData(true, ticksDisplayed);
		timePanel.setTimeLadderParams(ticksDisplayed);	
	}
	
	public int convertXValueOnRef(int value) {
		double amplitudeX = displayDataList.getxMaxView() - displayDataList.getxMinView();
		double ratioX = (timePanel.getBounds().getWidth()-timePanel.getBounds().getWidth()/3) / amplitudeX;
		int newX = (int) ((value - displayDataList.getxMinView()) * ratioX);
		return newX;
	}
	
	private SortedMap<Integer, TimeTick> buildTicksInView(int tMin, int tMax){
		SortedMap<Integer, TimeTick> ticksInView = Collections.synchronizedSortedMap(new TreeMap<Integer, TimeTick>());
		HashMap<Integer, TimeTick> allTicks = timeData.getTimeTicks();
		
		Iterator<Integer> iter = allTicks.keySet().iterator();
		while(iter.hasNext()){
			int currentFrame = iter.next();
			if(currentFrame>=tMin && currentFrame<=tMax){
				ticksInView.put(currentFrame, allTicks.get(currentFrame));
			}
		}
		return ticksInView;
	}

	
	public static String[] frame2HMSInTab(int frame){//TODO A supprimer
		int[]HMS = TimeHMSConvertor.frame2HMS(frame);
		String[]res = new String[3];
		res[0] = Integer.toString(HMS[0]);
		res[1] = Integer.toString(HMS[1]);
		res[2] = Integer.toString(HMS[2]);
		
		return res;
	}
	
	public static String frame2HMS(int frame){		//TODO A supprimer
		int[]HMS = TimeHMSConvertor.frame2HMS(frame);
		return HMS[0]+":"+HMS[1]+":"+HMS[2];

	}

	public void setTimeData(TimeData timeData) {
		this.timeData = timeData;
	}

	public TimeData getTimeData() {
		return timeData;
	}
}
